package com.sentiment.database.dbUtil;

import static com.mongodb.client.model.Filters.and;
import static com.mongodb.client.model.Filters.gt;
import static com.mongodb.client.model.Filters.lt;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import org.bson.Document;
import org.bson.codecs.CollectibleCodec;
import org.bson.codecs.configuration.CodecRegistries;
import org.bson.codecs.configuration.CodecRegistry;
import org.bson.types.ObjectId;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.mongodb.Block;
import com.mongodb.MongoClient;
import com.mongodb.client.FindIterable;
import com.mongodb.client.MongoCollection;
import com.mongodb.client.MongoCursor;
import com.mongodb.client.MongoDatabase;
import com.mongodb.client.result.DeleteResult;
import com.mongodb.client.result.UpdateResult;
import com.sentiment.config.ConfigDb;
import com.sentiment.database.bean.CrawlNews;
import com.sentiment.database.codec.CrawlNewsCodec;

public class DbCodecDriver<T extends Document> {
	private static final Logger LOG = LoggerFactory.getLogger(DbCodecDriver.class);
	private MongoClient client;
	private MongoDatabase db;
	private MongoCollection<T> collection;

	public static void main(String[] args) {
		DbCodecDriver<CrawlNews> driver = new DbCodecDriver<CrawlNews>();
		driver.openConnection(ConfigDb.sentimentDb, CrawlNews.class, CrawlNewsCodec.class);
		CrawlNews n = new CrawlNews(null, null, null, null, Arrays.asList("11"), null, "搜狐", null, null, null, null, null);
		
		List<CrawlNews> list = driver.queryMany(n);
		System.out.println(list.size());
		driver.closeConnection();
	}
public DbCodecDriver() {
	// TODO Auto-generated constructor stub
	
}
	/**
	 * 传入数据库名和bean对象的class
	 * 
	 * @param dbName
	 * @param claz
	 */
	@SuppressWarnings("rawtypes")
	public void openConnection(String dbName, Class<T> claz, Class<? extends CollectibleCodec> codecClaz) {
		// TODO Auto-generated method stub
		CodecRegistry registry = null;
		try {
			registry = CodecRegistries.fromCodecs(codecClaz.newInstance());
		} catch (InstantiationException e) {
			// TODO Auto-generated catch block
			LOG.error(e.toString());
		} catch (IllegalAccessException e) {
			// TODO Auto-generated catch block
			LOG.error(e.toString());
		}
		client = new MongoClient();
		db = client.getDatabase(dbName);
		if (registry == null) {
			LOG.error("  registry is null !");
			return;
		}
		collection = db.withCodecRegistry(registry).getCollection(claz.getSimpleName(), claz);
	}

	public void closeConnection() {
		// TODO Auto-generated method stub
		client.close();
	}

	/**
	 * 根据页码和每页显示数返回该表中的数据
	 * @param pageNum 页码
	 * @param count 每页显示数
	 * @return
	 */
	public List<T> getPage(Integer pageNum , Integer count){
		FindIterable<T> it = collection.find();
		MongoCursor<T> cursor = it.iterator();
		int sum = (pageNum-1) * count;
		List<T> li = new ArrayList<T>();
		while(cursor.hasNext()){
			if(sum > 0 && cursor.hasNext()){
				cursor.next();
				sum--;
			}
			else if(li.size() < count && cursor.hasNext()){
				li.add(cursor.next());
			}
			else{
				break;
			}
		}
		return li;
	}
	
	public boolean insert(T t) {
		// TODO Auto-generated method stub
		collection.insertOne(t);
		return true;
	}
	public ObjectId insertGetId(T t){
		collection.insertOne(t);
		return t.getObjectId("_id");
	}

	public boolean insertNotExist(T t) {
		// TODO Auto-generated method stub
		if (collection.find(t).first() == null) {
			collection.insertOne(t);
			return true;
		} else
			return false;
	}

	public boolean insertMany(List<T> list) {
		// TODO Auto-generated method stub
		collection.insertMany(list);
		return true;
	}

	public boolean insertManyNotExist(List<T> list) {
		// TODO Auto-generated method stub
		for (T t : list) {
			if (!insertNotExist(t))
				return false;
		}
		return true;
	}

	public T query(T t) {
		// TODO Auto-generated method stub
		T rt = collection.find(t).first();
		return rt;
	}

	public List<T> queryMany(T t) {
		// TODO Auto-generated method stub
		final List<T> list = new ArrayList<T>();

		Block<T> block = new Block<T>() {

			@Override
			public void apply(final T u) {
				// TODO Auto-generated method stub
				list.add(u);
			}
		};

		collection.find(t).forEach(block);
		return list;
	}

	/**
	 * 
	 * @param fieldName
	 *            需要查询的key
	 * @param startValue
	 *            查询的最小值
	 * @param endValue
	 *            查询的最大值
	 * @return
	 */
	public List<T> queryMany(String fieldName, Object startValue, Object endValue) {
		// TODO Auto-generated method stub
		final List<T> list = new ArrayList<T>();
		Block<T> block = new Block<T>() {

			@Override
			public void apply(final T u) {
				list.add(u);
			}
		};
		collection.find(and(gt(fieldName, startValue), lt(fieldName, endValue))).forEach(block);
		return list;
	}

	public boolean remove(T t) {
		// TODO Auto-generated method stub
		DeleteResult result = collection.deleteOne(t);
		return result.getDeletedCount() != 0;
	}

	public long removeMany(T t) {
		// TODO Auto-generated method stub
		DeleteResult result = collection.deleteMany(t);
		return result.getDeletedCount();
	}

	/**
	 * 所有update用法要注意更新文档外必须再包一层更新方法的文档
	 * @param target
	 *            指向待更新的文档
	 * @param update
	 *            更新的文档
	 * @return
	 */
	public boolean update(T target, T update) {
		// TODO Auto-generated method stub
		UpdateResult result = collection.updateOne(target, update);
		return result.getModifiedCount() != 0;
	}
/**
 * 所有update用法要注意更新文档外必须再包一层更新方法的文档
 * @param target
 * @param update
 * @return
 */
	public long updateMany(T target, T update) {
		// TODO Auto-generated method stub
		UpdateResult result = collection.updateMany(target, update);
		return result.getModifiedCount();
	}

	public long getCollectionCount() {
		// TODO Auto-generated method stub
		return collection.count();
	}
}
